package com.microservice.skeleton.upms.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.javadoc.*;
import com.sun.tools.doclets.standard.Standard;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import static com.microservice.skeleton.upms.config.JavadocJsonExtractor.DocletOptionParser.JAVA_DOC_DIR_OPTION;
import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * @author: lijin
 * @date: 2018年10月31日
 */
public class JavadocJsonExtractor extends Standard {

    public static String javadocJsonDir = null;
    public static boolean start(RootDoc root) {

        String destinationDir = javadocJsonDir;
        ObjectMapper mapper = createObjectMapper();

        for (ClassDoc classDoc : root.classes()) {
            ClassJavadoc cd = ClassJavadoc.fromClassDoc(classDoc);
            writeToFile(destinationDir, mapper, classDoc, cd);

        }
        return true;
    }

    private static void writeToFile(String destinationDir, ObjectMapper mapper,
                                    ClassDoc classDoc, ClassJavadoc cd) {

        try {
            Path path = path(destinationDir, classDoc);
            System.out.println(path);
            try (BufferedWriter writer = Files.newBufferedWriter(path, UTF_8)) {
                mapper.writerFor(ClassJavadoc.class).writeValue(writer, cd);
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("Error writing file: " + e);
        }
    }


    private static Path path(String destinationDir, ClassDoc classDoc) throws IOException {
        String packageName = classDoc.containingPackage().name();
        String packageDir = packageName.replace(".", File.separator);
        Path packagePath = Paths.get(packageDir);

        final Path path;
        if (destinationDir != null) {
            path = Paths.get(destinationDir).resolve(packageDir);
        } else {
            path = packagePath;
        }

        Files.createDirectories(path);

        return path.resolve(classDoc.name() + ".json");
    }

    private static ObjectMapper createObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(mapper.getSerializationConfig().getDefaultVisibilityChecker()
                .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
                .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
        return mapper;
    }

    public static boolean validOptions(
            String[][] options,
            DocErrorReporter reporter) {

        DocletOptionParser parser = new DocletOptionParser(options);

        try {
            javadocJsonDir = parser.parse();
            return true;
        } catch (IllegalStateException e) {
            reporter.printError(e.getMessage());
        }
        return false;
    }

    public static int optionLength(String option) {
        int length = 0;
        if (option.equalsIgnoreCase(JAVA_DOC_DIR_OPTION)) {
            length = 2;
        }
        return length;
    }
    static class DocletOptionParser {
        static final String JAVA_DOC_DIR_OPTION = "-javadocJsonDir";
        private final String[][] options;

        DocletOptionParser(String[][] options) {
            this.options = options;
        }

        String parse() {
            String javadocJsonDir = "";
            for (String[] each : options) {
                if (JAVA_DOC_DIR_OPTION.equalsIgnoreCase(each[0])) {
                    javadocJsonDir = each[1];
                }
            }

            return javadocJsonDir;
        }
    }


}
